skip checkRepoConfigInaccessible when git directory specified explicitly
authorJoey Hess <joeyh@joeyh.name>
Tue, 20 Sep 2022 18:52:43 +0000 (14:52 -0400)
committerJoey Hess <joeyh@joeyh.name>
Tue, 20 Sep 2022 18:52:43 +0000 (14:52 -0400)
Fix a reversion that prevented git-annex from working in a repository when
--git-dir or GIT_DIR is specified to relocate the git directory to
somewhere else. (Introduced in version 10.20220525)

checkRepoConfigInaccessible could still run git config --list, just passing
--git-dir. It seems not necessary, because I know that passing --git-dir
bypasses git's check for repo ownership. I suppose it might be that git
eventually changes to check something about the ownership of the working
tree, so passing --git-dir without --work-tree would still be worth doing.
But for now this is the simple fix.

Sponsored-by: Nicholas Golder-Manning on Patreon
CHANGELOG
Git/Config.hs
Git/Construct.hs
Git/CurrentRepo.hs
Git/Types.hs
doc/bugs/When_--git-dir_is_not_in_--work-tree.mdwn

index c054007290bc6d2c73576eb9a1e44d7c77dedb82..56593f35cce0eaa69fc9298f5918a20cfa4be740 100644 (file)
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -23,6 +23,10 @@ git-annex (10.20220823) UNRELEASED; urgency=medium
     that it had changed, due to only accepting the inode+mtime of one file
     (that was since modified or deleted) and not accepting the inode+mtime
     of other duplicate files.
+  * Fix a reversion that prevented git-annex from working in a
+    repository when --git-dir or GIT_DIR is specified to relocate the git
+    directory to somewhere else.
+    (Introduced in version 10.20220525)
 
  -- Joey Hess <id@joeyh.name>  Mon, 29 Aug 2022 15:03:04 -0400
 
index 7fd096d1f869db6db5e91e04c820002e50da8dab..7bf27937784dad68dbf5254b2edd4a314058a9ae 100644 (file)
@@ -282,16 +282,20 @@ unset ck@(ConfigKey k) r = ifM (Git.Command.runBool ps r)
  - repo.
  -}
 checkRepoConfigInaccessible :: Repo -> IO Bool
-checkRepoConfigInaccessible r = do
-       -- Cannot use gitCommandLine here because specifying --git-dir
-       -- will bypass the git security check.
-       let p = (proc "git" ["config", "--local", "--list"])
-               { cwd = Just (fromRawFilePath (repoPath r))
-               , env = gitEnv r
-               }
-       (out, ok) <- processTranscript' p Nothing
-       if not ok
-               then do
-                       debug (DebugSource "Git.Config") ("config output: " ++ out)
-                       return True
-               else return False
+checkRepoConfigInaccessible r
+       -- When --git-dir or GIT_DIR is used to specify the git
+       -- directory, git does not check for CVE-2022-24765.
+       | gitDirSpecifiedExplicitly r = return False
+       | otherwise = do
+               -- Cannot use gitCommandLine here because specifying --git-dir
+               -- will bypass the git security check.
+               let p = (proc "git" ["config", "--local", "--list"])
+                       { cwd = Just (fromRawFilePath (repoPath r))
+                       , env = gitEnv r
+                       }
+               (out, ok) <- processTranscript' p Nothing
+               if not ok
+                       then do
+                               debug (DebugSource "Git.Config") ("config output: " ++ out)
+                               return True
+                       else return False
index a5e825e7c35e51dadc9adb65ba4e324725d2c6d3..27123e337d86dcee7a819856695d46d8a6361335 100644 (file)
@@ -277,5 +277,6 @@ newFrom l = Repo
        , gitEnv = Nothing
        , gitEnvOverridesGitDir = False
        , gitGlobalOpts = []
+       , gitDirSpecifiedExplicitly = False
        }
 
index 9261eabca1895cb4833802a402c47fe7dc386038..bd1ab5cd4b6dd1938ad6b3b841896cfb1736e92b 100644 (file)
@@ -1,6 +1,6 @@
 {- The current git repository.
  -
- - Copyright 2012-2020 Joey Hess <id@joeyh.name>
+ - Copyright 2012-2022 Joey Hess <id@joeyh.name>
  -
  - Licensed under the GNU AGPL version 3 or higher.
  -}
@@ -80,9 +80,10 @@ get = do
                        , worktree = Just curr
                        }
                r <- Git.Config.read $ newFrom loc
-               return $ if Git.Config.isBare r
-                       then r { location = (location r) { worktree = Nothing } }
-                       else r
+               let r' = r { gitDirSpecifiedExplicitly = True }
+               return $ if Git.Config.isBare r'
+                       then r' { location = (location r) { worktree = Nothing } }
+                       else r'
        configure Nothing Nothing = giveup "Not in a git repository."
 
        addworktree w r = changelocation r $ Local
index 68045fc02746b9049f170bf9f83666c3b8c0cbad..ce1818e71c8527dcf8e54fbadfb70cfc26e0e97f 100644 (file)
@@ -51,6 +51,8 @@ data Repo = Repo
        , gitEnvOverridesGitDir :: Bool
        -- global options to pass to git when running git commands
        , gitGlobalOpts :: [CommandParam]
+       -- True only when --git-dir or GIT_DIR was used
+       , gitDirSpecifiedExplicitly :: Bool
        } deriving (Show, Eq, Ord)
 
 newtype ConfigKey = ConfigKey S.ByteString
index 35d13758a2ff337d4b306483c962b692c1efddb2..dbc430b22c38c2667ad3bfa60198d9a8a37fe6a7 100644 (file)
@@ -18,3 +18,35 @@ Simple test case:
 
         failed
 
+And --debug shows:
+
+       [2022-09-20 14:17:56.238686901] (Utility.Process) process [1284622] read: git ["config","--local","--list"]
+       [2022-09-20 14:17:56.240836887] (Utility.Process) process [1284622] done ExitFailure 128
+       [2022-09-20 14:17:56.24107763] (Git.Config) config output: fatal: --local can only be used inside a git repository
+
+So passing --git-dir to that command will make it succeeed. The problem
+though is that passing --git-dir to that command also bypasses git's
+fix for CVE-2022-24765. The command would even succeed if the directory
+were owned by someone else then.
+
+       joey@darkstar:/tmp/foo>sudo chown -R root.root .
+       [sudo] password for joey:
+       joey@darkstar:/tmp/foo>git --git-dir=`pwd`/.dotfiles config --local --list
+       core.repositoryformatversion=0
+       core.filemode=true
+       core.bare=false
+       core.logallrefupdates=true
+       core.worktree=/tmp/foo
+       joey@darkstar:/tmp/foo>git config --local --list
+       fatal: --local can only be used inside a git repository
+
+But, if the user runs git-annex with an explicit --git-dir,
+it's actually ok for git-annex to bypass the CVE-2022-24765 check.
+Because --git-dir actually bypasses that check.
+
+So, the fix for this seems like it will involve it remembering
+when the git repo was originally specified using --git-dir (or `GIT_DIR`),
+and if so, guardSafeToUseRepo can skip the check, or pass --git-dir to
+`git config --local --list`.
+
+> [[fixed|done]] --[[Joey]]